#include "../src/ClientRPC/RPCClientPort.hpp"
#include <cstdint>
#include <iostream>
#include <thrift/Thrift.h>

int main() {
  std::cout << ">>>>>> ControlClient Initialized" << std::endl;
  std::string PeerAddr;
  long PeerPort;
  std::cout << "Enter RPC Server Addr: ";
  std::cin >> PeerAddr;
  std::cout << "Enter RPC Server Port: ";
  std::cin >> PeerPort;

  RPCClientPort client(PeerAddr, PeerPort);
  client.Boot();

  std::cout << "<<<<<< ControlClient Ready" << std::endl;
  bool runflag = true;
  while (runflag) {
    std::cout << R"(
      Menu:
      0. Exit
      1. StartShot
      2. StopShot
      3. ShotStatus
      4. StartRecord
      5. StopRecord
      6. RecordStatus
      7. GetAllDevice
      8. GetAllFormat
      9. GetSettingList
      10. GetSettingValue
      11. SetSettingValue
      12. GetShareMemInfo
      13. GetPreviewImageInfo
      14. OfflineCamera
    )" << std::endl;
    std::cout << "Enter your select: ";
    int selectitem;
    std::cin >> selectitem;

    try {
      switch (selectitem) {
      case 0: {
        runflag = false;
      } break;
      case 1: {
        std::string UUID;
        std::cout << "Enter UUID: ";
        std::cin >> UUID;
        client.StartShot(UUID);
      } break;
      case 2: {
        std::string UUID;
        std::cout << "Enter UUID: ";
        std::cin >> UUID;
        client.StopShot(UUID);
      } break;
      case 3: {
        std::string UUID;
        std::cout << "Enter UUID: ";
        std::cin >> UUID;
        std::cout << (client.ShotStatus(UUID) ? "True" : "False") << std::endl;
      } break;
      case 4: {
        std::string UUID, savepath;
        int16_t index;
        std::cout << "Enter UUID: ";
        std::cin >> UUID;
        std::cout << "Enter savepath: ";
        std::cin >> savepath;
        std::cout << "Enter index: ";
        std::cin >> index;
        client.StartRecord(UUID, savepath, index);
      } break;
      case 5: {
        std::string UUID;
        std::cout << "Enter UUID: ";
        std::cin >> UUID;
        client.StopRecord(UUID);
      } break;
      case 6: {
        std::string UUID;
        std::cout << "Enter UUID: ";
        std::cin >> UUID;
        std::cout << (client.RecordStatus(UUID) ? "True" : "False")
                  << std::endl;
      } break;
      case 7: {
        std::set<std::string> res;
        client.GetAllDevice(res);
        std::cout << "Device List: " << std::endl;
        for (auto &i : res)
          std::cout << '\t' << i << std::endl;
      } break;
      case 8: {
        std::map<int16_t, std::string> res;
        client.GetAllFormat(res);
        std::cout << "Format List: " << std::endl;
        std::cout << "index\tname\t" << std::endl;
        for (auto &[index, name] : res)
          std::cout << '\t' << index << '\t' << name << std::endl;
      } break;
      case 9: {
        std::string res, UUID;
        std::cout << "Enter UUID: ";
        std::cin >> UUID;
        client.GetSettingList(res, UUID);
        std::cout << "Result: " << std::endl << res << std::endl;
      } break;
      case 10: {
        std::string UUID, res;
        int32_t index;
        std::cout << "Enter UUID: ";
        std::cin >> UUID;
        std::cout << "Enter Index: ";
        std::cin >> index;
        client.GetSettingValue(res, UUID, index);
        std::cout << "Result: " << std::endl << res << std::endl;
      } break;
      case 11: {
        std::string UUID, Conf;
        std::cout << "Enter UUID: ";
        std::cin >> UUID;
        std::cout << "Enter Conf: ";
        std::cin >> Conf;
        std::cout << (client.SetSettingValue(UUID, Conf) ? "True" : "False")
                  << std::endl;
      } break;
      case 12: {
        std::string UUID, res;
        std::cout << "Enter UUID: ";
        std::cin >> UUID;
        client.GetShareMemInfo(res, UUID);
        std::cout << "Result: " << std::endl << res << std::endl;
      } break;
      case 13: {
        std::string UUID, res;
        std::cout << "Enter UUID: ";
        std::cin >> UUID;
        client.GetPreviewImageInfo(res, UUID);
        std::cout << "Result: " << std::endl << res << std::endl;
      } break;
      case 14: {
        std::string UUID;
        std::cout << "Enter UUID: ";
        std::cin >> UUID;
        client.OfflineCamera(UUID);
      } break;
      default:
        std::cout << "Unknow Command, Retry" << std::endl;
      }
    } catch (const apache::thrift::TException &e) {
      std::cout << "Catch Thrift Exception : " << e.what() << std::endl;
    } catch (const std::exception &e) {
      std::cout << "Catch Unknow Exception : " << e.what() << std::endl;
    }
  }
}
